/********************************************************************************
 * Project Name		[JavaEE_Web]
 * File Name     	[ResponseZipFilter.java]
 * Creation Date 	[2015-01-01]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ********************************************************************************/
package filter.cases;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;

import javax.servlet.DispatcherType;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import filter.HttpFilter;

/**
 * 压缩过滤器, 将Web应用中的JS, HTML, CSS都压缩后再输出浏览器
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 * 
 */
@WebFilter(filterName = "BufferedResponseFilter", urlPatterns = { "*.js", "*.css", "*.html",
		"*.htm" }, dispatcherTypes = { DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE })
public class BufferedResponseFilter extends HttpFilter {

	@Override
	public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws IOException, ServletException {
		BufferedResponse bufferedResponse = new BufferedResponse(response);
		filterChain.doFilter(request, bufferedResponse);

		// 从缓存中拿出数据
		byte[] data = bufferedResponse.getBuffer();
		System.out.println("原始大小: " + data.length);

		// 压缩输出流中的数据
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		GZIPOutputStream zipOutputSteam = new GZIPOutputStream(outputStream);
		zipOutputSteam.write(data);
		zipOutputSteam.close();

		byte[] zipData = outputStream.toByteArray();
		System.out.println("压缩后大小:" + zipData.length);
		response.setHeader("content-encoding", "gzip");
		response.setContentLength(zipData.length);
		response.getOutputStream().write(zipData);
	}
}

/**
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 *
 */
class BufferedResponse extends HttpServletResponseWrapper {

	private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
	private PrintWriter writer;
	private HttpServletResponse response;

	public BufferedResponse(HttpServletResponse response) {
		super(response);
		this.response = response;
	}

	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		return new BufferedServletOutputStream(outputStream);
	}

	@Override
	public PrintWriter getWriter() throws IOException {
		writer = new PrintWriter(new OutputStreamWriter(outputStream, this.response.getCharacterEncoding()));
		return writer;
	}

	public byte[] getBuffer() {
		try {
			if (writer != null) {
				writer.close();
			}
			if (outputStream != null) {
				outputStream.flush();
				return outputStream.toByteArray();
			}

			return null;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

/**
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 *
 */
class BufferedServletOutputStream extends ServletOutputStream {

	private ByteArrayOutputStream outputStream;

	public BufferedServletOutputStream(ByteArrayOutputStream outputStream) {
		this.outputStream = outputStream;
	}

	@Override
	public boolean isReady() {
		return false;
	}

	@Override
	public void setWriteListener(WriteListener listener) {

	}

	@Override
	public void write(int b) throws IOException {
		this.outputStream.write(b);
	}
}
